package com.nhncorp.pleiades.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class PipeCommander {
  public static final Log LOG = LogFactory.getLog(PipeCommander.class
      .getName()); 
  
  public static void main(String[] args) {
    PipeCommander commander = new PipeCommander();
    try {
      commander.runSimpleCommand(args[0]);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void runSimpleCommand(String cmd) throws IOException {
    LOG.info("Starting to run shell command: " + cmd);
    Process process;
    String[] params = new String[3];
    params[0] = "sh";
    params[1] = "-c";
    params[2] = cmd;
    process = Runtime.getRuntime().exec(params);

    try {
      if (process.waitFor() != 0) {
        throw new IOException(new BufferedReader(new InputStreamReader(process
            .getErrorStream())).readLine());
      }
      parseExecResult(new BufferedReader(new InputStreamReader(process
          .getInputStream())));
    } catch (InterruptedException e) {
      throw new IOException(e.toString());
    } finally {
      process.destroy();
    }
  }

  protected void parseExecResult(BufferedReader lines) throws IOException {
    boolean isFirstLine = true;
    while (lines.ready()) {
      String line = lines.readLine();
      if (line == null && isFirstLine) {
        throw new IOException("Expecting a line not the end of stream");
      }
      LOG.info(line);
      isFirstLine = false;
    }
  }
  
  public String runShellCommand(String cmd) throws IOException {
    LOG.info("Starting to run shell command: " + cmd);
    String[] params = new String[3];
    params[0] = "sh";
    params[1] = "-c";
    params[2] = cmd;
    Process p = Runtime.getRuntime().exec(params);
    StringBuffer commandResult = new StringBuffer();
    final BufferedReader inR = new BufferedReader(new InputStreamReader(p
        .getInputStream()));
    final BufferedReader errR = new BufferedReader(new InputStreamReader(p
        .getErrorStream()));

    // read & log any error messages from the running shell command
    Thread errThread = new Thread() {
      
      public void start() {
        try {
          String errLine = errR.readLine();
          while (errLine != null) {
            LOG.warn("shell command error: " + errLine);
            errLine = errR.readLine();
          }
        } catch (IOException e) {
        }
      }
    };
    try {
      errThread.start();

      // fetch output from the process
      String line = inR.readLine();
      while (line != null) {
        commandResult.append(line);
        line = inR.readLine();
      }
      try {
        // wait for the process to finish
        int returnVal = p.waitFor();
        // check the exit code
        if (returnVal != 0) {
          throw new IOException("Process exits with nonzero status: " + cmd);
        }
      } catch (InterruptedException e) {
        throw new IOException(e.getMessage());
      } finally {
        try {
          // make sure that the error thread exits
          errThread.join();
        } catch (InterruptedException je) {
          LOG.warn(StringUtils.stringifyException(je));
        }
      }
    } finally {
      // close in & error streams
      try {
        inR.close();
      } catch (IOException ine) {
        throw ine;
      } finally {
        errR.close();
      }
    }
    
    return commandResult.toString();
  }  

}
